package com.kelin.calendarlistview.library;

import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.window.service.DisplayManager;

import ohos.app.Context;

import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;

import java.io.IOException;

import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;

/**
 * BaseCalendarItemAdapter
 * @param <T>
 */
public class BaseCalendarItemAdapter<T extends BaseCalendarItemModel> extends BaseItemProvider {
    private static final int WEEK_NUM = 7;
    protected Context mContext;
    //key:date("yyyy-MM-dddd"),value: you custom CalendarItemModel must extend BaseCalendarItemModel
    protected TreeMap<String, T> dayModelList = new TreeMap<>();
    //list to keep dayModelList's key that convenient for get key by index.
    protected List<String> indexToTimeMap = new ArrayList<>();
    ;
    protected Component.ClickedListener gridClickedListener;

    /**
     * BaseCalendarItemAdapter instance
     *
     * @param context 上下文
     */
    public BaseCalendarItemAdapter(Context context) {
        this.mContext = context;
    }

    /**
     * getDayModelList
     *
     * @return TreeMap<String, T>
     */
    public TreeMap<String, T> getDayModelList() {
        return dayModelList;
    }

    /**
     * setDayModelList
     *
     * @param dayModelList TreeMap<String, T>
     */
    public void setDayModelList(TreeMap<String, T> dayModelList) {
        this.dayModelList = dayModelList;
        indexToTimeMap.clear();
        for (String time : this.dayModelList.keySet()) {
            indexToTimeMap.add(time);
        }
    }

    /**
     * getIndexToTimeMap
     *
     * @return List<String>
     */
    public List<String> getIndexToTimeMap() {
        return indexToTimeMap;
    }

    /**
     * setGridClickedListener
     *
     * @param listener listener
     */
    public void setGridClickedListener(Component.ClickedListener listener) {
        gridClickedListener = listener;
    }

    @Override
    public int getCount() {
        int size = dayModelList.size();
        int remainder = size % WEEK_NUM;
        int cnt = (size - remainder) / WEEK_NUM;
        cnt = remainder > 0 ? cnt + 1 : cnt;
        return cnt;
    }

    @Override
    public Object getItem(int position) {
        if (position >= dayModelList.size()) {
            return null;
        }
        String date = indexToTimeMap.get(position);
        return dayModelList.get(date);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    /**
     * default calendar item view，We are appreciate of you override this function to custom your View items.
     * getView
     *
     * @param date date
     * @param model model
     * @param convertView Component
     * @param parent ComponentContainer
     * @return Component
     */
    public Component getView(String date, T model, Component convertView, ComponentContainer parent) {
        Component view = convertView;
        if (view == null) {
            view = LayoutScatter.getInstance(mContext).parse
                    (ResourceTable.Layout_griditem_calendar_item, null, false);
        }
        Text dayNum = (Text) view.findComponentById(ResourceTable.Id_tv_day_num);
        dayNum.setText(model.getDayNumber());

        view.setBackground(new ShapeElement(view.getContext(), ResourceTable.Graphic_bg_shape_calendar_item_normal));

        Color redColor = Color.RED;
        Color graybColor = Color.GRAY;
        try {
            redColor = new Color(mContext.getResourceManager().getElement(ResourceTable.Color_red_ff725f).getColor());
            graybColor = new Color(mContext.getResourceManager().getElement(ResourceTable.Color_gray_bbbbbb).getColor());
        } catch (IOException | NotExistException | WrongTypeException e) {
            e.printStackTrace();
        }

        if (model.isToday()) {
            dayNum.setTextColor(redColor);
            dayNum.setText(ResourceTable.String_today);
        }

        if (model.isHoliday()) {
            dayNum.setTextColor(redColor);
        }

        if (model.getStatus() == BaseCalendarItemModel.Status.DISABLE) {
            dayNum.setTextColor(Color.DKGRAY);
        }

        if (!model.isCurrentMonth()) {
            dayNum.setTextColor(graybColor);
            view.setClickable(true);
        }

        return view;
    }

    @Override
    public Component getComponent(int position, Component convertView, ComponentContainer parent) {
        Component view = convertView;
        final ViewHolder holder;
        if (convertView == null) {
            view = LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_gridview_item, parent, false);
            holder = new ViewHolder();
            holder.layouts = new ArrayList<>();
            holder.layouts.add((DirectionalLayout) view.findComponentById(ResourceTable.Id_item_1));
            holder.layouts.add((DirectionalLayout) view.findComponentById(ResourceTable.Id_item_2));
            holder.layouts.add((DirectionalLayout) view.findComponentById(ResourceTable.Id_item_3));
            holder.layouts.add((DirectionalLayout) view.findComponentById(ResourceTable.Id_item_4));
            holder.layouts.add((DirectionalLayout) view.findComponentById(ResourceTable.Id_item_5));
            holder.layouts.add((DirectionalLayout) view.findComponentById(ResourceTable.Id_item_6));
            holder.layouts.add((DirectionalLayout) view.findComponentById(ResourceTable.Id_item_7));
            Point pt = new Point();
            DisplayManager.getInstance().getDefaultDisplay(mContext).get().getSize(pt);
            int width = (int) pt.getPointX() / WEEK_NUM;
            for (int i = 0; i < WEEK_NUM; i++) {
                holder.layouts.get(i).setComponentSize(width, width);
            }
            view.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }

        int rank = position * WEEK_NUM;
        for (int r = 0; r < WEEK_NUM; r++) {
            int pos = rank + r;
            DirectionalLayout itemLayout = holder.getItemLayout(r);
            if (itemLayout.getChildCount() > 1) {
                itemLayout.removeComponents(1, itemLayout.getChildCount() - 1);
            }

            if (getItem(pos) == null) {
                itemLayout.setVisibility(Component.INVISIBLE);
            } else {
                itemLayout.setVisibility(Component.VISIBLE);
                itemLayout.setTag(new TagPosition(pos));
                if (gridClickedListener != null) {
                    itemLayout.setClickedListener(gridClickedListener);
                }
                String date = indexToTimeMap.get(pos);
                Component child = getView(date, dayModelList.get(date), convertView, parent);
                ComponentContainer.LayoutConfig layoutParams = new ListContainer.LayoutConfig(CalendarView.getmItemWidth(), CalendarView.getmItemHeight());
                child.setLayoutConfig(layoutParams);
                itemLayout.addComponent(child);
            }
        }

        return view;
    }

    /**
     * ViewHolder
     */
    private static class ViewHolder {
        private ArrayList<DirectionalLayout> layouts;

        /**
         * getItemLayout
         *
         * @param pos pos
         * @return layouts
         */
        public DirectionalLayout getItemLayout(int pos) {
            return layouts.get(pos);
        }
    }

    /**
     * TagPosition
     */
    public static class TagPosition {
        private int pos;

        /**
         * TagPosition instance
         *
         * @param pos pos
         */
        public TagPosition(int pos) {
            this.pos = pos;
        }

        /**
         * getPos
         *
         * @return this.pos
         */
        public int getPos() {
            return this.pos;
        }
    }

}
